﻿#include "kv_store.h"

const char *Command[] = {
    "SET", "GET", "DEL", "MOD", "EXIST",
    "RSET", "RGET", "RDEL", "RMOD", "REXIST",
    "SSET", "SGET", "SDEL", "SMOD", "SEXIST",
    "HSET", "HGET", "HDEL", "HMOD", "HEXIST"
};

// 命令类型
enum COMMAND
{
    CMD_STATUS_START = 0,

    CMD_STATUS_SET = CMD_STATUS_START,
    CMD_STATUS_GET,
    CMD_STATUS_DEL,
    CMD_STATUS_MOD,
    CMD_STATUS_EXIST,

    CMD_STATUS_RSET,
    CMD_STATUS_RGET,
    CMD_STATUS_RDEL,
    CMD_STATUS_RMOD,
    CMD_STATUS_REXIST,

    CMD_STATUS_SSET,
    CMD_STATUS_SGET,
    CMD_STATUS_SDEL,
    CMD_STATUS_SMOD,
    CMD_STATUS_SEXIST,

    CMD_STATUS_HSET,
    CMD_STATUS_HGET,
    CMD_STATUS_HDEL,
    CMD_STATUS_HMOD,
    CMD_STATUS_HEXIST,

    CMD_STATUS_NUMBER
};

int kvs_split_token(char *msg, char *tokens[])
{
    int idx = 0;
    char *token = strtok(msg, " ");
    while (token != NULL)
    {
        tokens[idx++] = token;
#ifdef PRINTFCMODE
        printf("token:%s\n", token);
#endif
        token = strtok(NULL, " ");
    }
    return idx;
}

int kvs_parse_protocol(char *tokens[], int tokenslen, char *Sendbuff)
{
    if (tokens == NULL || tokenslen == 0 || Sendbuff == NULL)
    {
        return -1;
    }

    int cmd = CMD_STATUS_START;
    for (int i = 0; i < tokenslen;)
    {
        int j = 0;
        for (j = cmd; j < CMD_STATUS_NUMBER; j++)
        {
            if (strcmp(tokens[i], Command[j]) == 0)
            {
                switch (j)
                {

#if ARRAYENGINEENABLE // 数组作为引擎

                case CMD_STATUS_SET:
                {
                    int res = kvs_array_set(&global_array, tokens[i + 1], tokens[i + 2]);
                    // printf("kvs_array_set_RES:%d\n",res);
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == 1)
                        sprintf(Sendbuff, "EXIST\n");
                    else
                        sprintf(Sendbuff, "ERROR\n");
                    printf("number:%d\n", global_array.total);
                    i += 3;
                }
                break;
                case CMD_STATUS_GET:
                {
                    char *getvalue = kvs_array_get(&global_array, tokens[i + 1]);
                    if (getvalue != NULL)
                        sprintf(Sendbuff, "%s\n", getvalue);
                    else
                        sprintf(Sendbuff, "%s\n", "NO EXIST"); 
                    i += 2;
                }
                break;
                case CMD_STATUS_DEL:
                {
                    int res = kvs_array_del(&global_array, tokens[i + 1]);
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    i += 2;
                }
                break;
                case CMD_STATUS_MOD:
                {
                    int res = kvs_array_mod(&global_array, tokens[i + 1], tokens[i + 2]);
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    i += 3;
                }
                break;
                case CMD_STATUS_EXIST:
                {
                    int res = kvs_array_exist(&global_array, tokens[i + 1]);
                    if (res == 0)
                        sprintf(Sendbuff, "NO\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    else
                        sprintf(Sendbuff, "YES\n");
                    i += 2;
                }
                break;
#elif RBTREEENGINEENABLE // 红黑树作为引擎


                case CMD_STATUS_RSET:
                {
                    int res = kvs_rbtree_set(&g_rbtree, tokens[i + 1], tokens[i + 2]);
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == 1)
                        sprintf(Sendbuff, "EXIST\n");
                    else
                        sprintf(Sendbuff, "ERROR\n");
                    i += 3;
                }
                break;
                case CMD_STATUS_RGET:
                {
                    char *getvalue = kvs_rbtree_get(g_rbtree, tokens[i + 1]);
                    if (getvalue != NULL)
                        sprintf(Sendbuff, "%s\n", getvalue);
                    else
                        sprintf(Sendbuff, "%s\n", "NO EXIST");
                    i += 2;
                }
                break;
                case CMD_STATUS_RDEL:
                {
                    int res = kvs_rbtree_del(&g_rbtree, tokens[i + 1]);
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    i += 2;
                }
                break;
                case CMD_STATUS_RMOD:
                {
                    int res = kvs_rbtree_mod(g_rbtree, tokens[i + 1], tokens[i + 2]);
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    i += 3;
                }
                break;
                case CMD_STATUS_REXIST:
                {
                    int res = kvs_rbtree_exist(g_rbtree, tokens[i + 1]);
                    if (res == 0)
                        sprintf(Sendbuff, "NO\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    else
                        sprintf(Sendbuff, "YES\n");
                    i += 2;
                }
                break;

#elif SKIPLISTENGINEENABLE // 跳表作为存储引擎

                case CMD_STATUS_SSET:
                {
                    int res = kvs_skiplist_set(g_skipList, tokens[i + 1], tokens[i + 2]);
                    if (res == 0)
                    {
#ifdef PRINTFCMODE
                        skiplist_print(g_skipList);
#endif
                        sprintf(Sendbuff, "OK\n");
                    }
                    else if (res == 1)
                        sprintf(Sendbuff, "EXIST\n");
                    else
                        sprintf(Sendbuff, "ERROR\n");
                    i += 3;
                }
                break;
                case CMD_STATUS_SGET:
                {
#ifdef PRINTFCMODE
                    skiplist_print(g_skipList);
#endif
                    char *getvalue = kvs_skiplist_get(g_skipList, tokens[i + 1]);
                    if (getvalue != NULL)
                        sprintf(Sendbuff, "%s\n", getvalue);
                    else
                        sprintf(Sendbuff, "%s\n", "NO EXIST");
                    i += 2;
                }
                break;
                case CMD_STATUS_SDEL:
                {
                    int res = kvs_skiplist_del(g_skipList, tokens[i + 1]);
#ifdef PRINTFCMODE
                    skiplist_print(g_skipList);
#endif
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    i += 2;
                }
                break;
                case CMD_STATUS_SMOD:
                {
                    int res = kvs_skiplist_mod(g_skipList, tokens[i + 1], tokens[i + 2]);
#ifdef PRINTFCMODE
                    skiplist_print(g_skipList);
#endif
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    i += 3;
                }
                break;
                case CMD_STATUS_SEXIST:
                {
                    int res = kvs_skiplist_exist(g_skipList, tokens[i + 1]);
#ifdef PRINTFCMODE
                    skiplist_print(g_skipList);
#endif
                    if (res == 0)
                        sprintf(Sendbuff, "NO\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    else
                        sprintf(Sendbuff, "YES\n");
                    i += 2;
                }
                break;
#elif HASHENGINEENABLE //哈希作为存储引擎
                case CMD_STATUS_HSET:
                {
                    int res = kvs_hash_set(g_hashTable, tokens[i + 1], tokens[i + 2]);
                    if (res == 0)
                    {
                        sprintf(Sendbuff, "OK\n");
                    }
                    else if (res == 1)
                        sprintf(Sendbuff, "EXIST\n");
                    else
                        sprintf(Sendbuff, "ERROR\n");
                    i += 3;
                }
                break;
                case CMD_STATUS_HGET:
                {
                    char *getvalue = kvs_hash_get(g_hashTable, tokens[i + 1]);
                    if (getvalue != NULL)
                        sprintf(Sendbuff, "%s\n", getvalue);
                    else
                        sprintf(Sendbuff, "%s\n", "NO EXIST");
                    i += 2;
                }
                break;
                case CMD_STATUS_HDEL:
                {
                    int res = kvs_hash_del(g_hashTable, tokens[i + 1]);
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    i += 2;
                }
                break;
                case CMD_STATUS_HMOD:
                {
                    int res = kvs_hash_mod(g_hashTable, tokens[i + 1], tokens[i + 2]);
                    if (res == 0)
                        sprintf(Sendbuff, "OK\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    i += 3;
                }
                break;
                case CMD_STATUS_HEXIST:
                {
                    int res = kvs_hash_exist(g_hashTable, tokens[i + 1]);
                    if (res == 0)
                        sprintf(Sendbuff, "NO\n");
                    else if (res == -1)
                        sprintf(Sendbuff, "Failed\n");
                    else
                        sprintf(Sendbuff, "YES\n");
                    i += 2;
                }
                break;

#endif
                default:
                    break;
                }
                break; // switch中的break只跳出switch语句
            }
        }
        i++;
    }
    return 0;
}

int ParserCallback(char *Recvbuff, char *Sendbuff)
{
#ifdef PRINTFCMODE
    printf("kv_store recv:%s\n", Recvbuff);
#endif
    // memcpy(Sendbuff,Recvbuff,strlen(Recvbuff));
    char *tokens[KVS_MAX_TOKEN] = {0};
    int tokenslen = kvs_split_token(Recvbuff, tokens);
    kvs_parse_protocol(tokens, tokenslen, Sendbuff);
	return 0;
}

#ifdef _WIN32
BOOL WINAPI funCall(DWORD dwCtrlType)
{
	switch (dwCtrlType)
	{
	case CTRL_CLOSE_EVENT:
		g_runFlag = FALSE;
		WaitForMultipleObjects(g_threadNumber, g_threadHead, TRUE, INFINITE);
		closeS();
		break;
	default:
		break;
	}
	return TRUE;
}
#endif

int main()
{
#ifdef __linux__
    pthread_t tid;
	void *status;
#endif

#ifdef _WIN32
	SetConsoleCtrlHandler(funCall, TRUE);
#endif

    //存储引擎
#if ARRAYENGINEENABLE
    kvs_array_create(&global_array);

#elif RBTREEENGINEENABLE
    kvs_rbtree_create();

#elif SKIPLISTENGINEENABLE
    kvs_skiplist_create();

#elif HASHENGINEENABLE
    kvs_hash_create();

#endif

    //网络框架
#if USAGEREACTOR
    SetCallbackFun_Reactor(ParserCallback);
    NetworkStart_Reactor(&tid);
#elif USAGEIOURING
    SetCallbackFun_Uring(ParserCallback);
    NetworkStart_Uring(&tid);
#elif USAGECOROUTINE
    SetCallbackFun_coroutine(ParserCallback);
    NetworkStart_coroutine(&tid);
#elif USAGEIOCP
	SetCallbackFun_IOCP(ParserCallback);
	InitComPort();
	createCompletePort();
	startThread();
#endif

	// 等待子线程结束  回收线程资源
#ifdef __linux__
    pthread_join(tid, &status); 
#endif
    return 0;
}
